home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / minix / libsrc~1.z / libsrc~1 / ctime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-12-28  |  9.1 KB  |  306 lines

  1. #include "lib.h"
  2. #include <sys/types.h>
  3. #include <time.h>
  4. #include <stdio.h>
  5.  
  6. #define toint(X)    (X - '0')
  7.  
  8.  
  9. static char             timebuf[26];
  10.  
  11. static char             *day[] =
  12.                         {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  13. static char             *month[] =
  14.                         {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  15.                         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  16. void tzset();
  17.  
  18. char *asctime(time)
  19.         register _CONST struct tm *time;
  20. /*
  21.  *      Convert <time> structure value to a string.  The same format, and
  22.  *      the same internal buffer, as for ctime() is used for this function.
  23.  */
  24.         {
  25.     if (time == NULL)
  26.          strcpy(timebuf, "??? ??? ?? ??:??:?? ????\n");
  27.     else
  28.              sprintf(timebuf, "%.3s %.3s%3d %02d:%02d:%02d %04d\n",
  29.                 day[time->tm_wday], month[time->tm_mon], time->tm_mday,
  30.                 time->tm_hour, time->tm_min, time->tm_sec, 1900+time->tm_year);
  31.         return(timebuf);
  32.         }
  33.  
  34. char *ctime(rawtime)
  35.         _CONST time_t *rawtime;
  36. /*
  37.  *      Convert <rawtime> to a string.  A 26 character fixed field string
  38.  *      is created from the raw time value.  The following is an example
  39.  *      of what this string might look like:
  40.  *              "Wed Jul 08 18:43:07 1987\n\0"
  41.  *      A 24-hour clock is used, and due to a limitation in the ST system
  42.  *      clock value, only a resolution of 2 seconds is possible.  A pointer
  43.  *      to the formatted string, which is held in an internal buffer, is
  44.  *      returned.
  45.  */
  46.         {
  47.         return(asctime(localtime(rawtime)));
  48.         }
  49.  
  50. /* mktime, localtime, gmtime */
  51. /* written by ERS and placed in the public domain */
  52.  
  53. #include <ctype.h>
  54.  
  55. #define SECS_PER_MIN    (60L)
  56. #define SECS_PER_HOUR   (60*SECS_PER_MIN)
  57. #define SECS_PER_DAY    (24*SECS_PER_HOUR)
  58. #define SECS_PER_YEAR   (365*SECS_PER_DAY)
  59. #define SECS_PER_LEAPYEAR (SECS_PER_DAY + SECS_PER_YEAR)
  60.  
  61. static
  62. int days_per_mth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  63.  
  64. static time_t tzoffset();
  65. static int    indst();
  66.  
  67. time_t timezone = -1;    /* holds # seconds west of GMT */
  68. static int dst = -1;    /* whether dst holds in current timezone */
  69.  
  70. /*
  71.  * FIXME: none of these routines is very efficient. Also, none of them
  72.  * handle dates before Jan 1, 1970.
  73.  *
  74.  */
  75.  
  76. /*
  77.  * mktime: take a time structure representing the local time (such as is
  78.  *  returned by localtime() and convert it into the standard representation
  79.  *  (as seconds since midnight Jan. 1 1970, GMT).
  80.  *
  81.  */
  82.  
  83. time_t
  84. mktime(t)
  85.         _CONST struct tm *t;
  86. {
  87.         time_t s;
  88.         int y;
  89.  
  90.         y = t->tm_year - 70;
  91.         if (y < 0)      /* year before 1970 */
  92.                 return (time_t) -1;
  93.         s = (SECS_PER_YEAR * y) + ( ((y+1)/4) * SECS_PER_DAY);
  94.                 /* extra days for leap years */
  95.         if ( (y+2)%4 )
  96.                 days_per_mth[1] = 28;
  97.         else
  98.                 days_per_mth[1] = 29;
  99.  
  100.         for (y = 0; y < t->tm_mon; y++)
  101.                 s += SECS_PER_DAY * days_per_mth[y];
  102.  
  103.         s += (t->tm_mday - 1) * SECS_PER_DAY;
  104.         s += t->tm_hour * SECS_PER_HOUR;
  105.         s += t->tm_min * SECS_PER_MIN;
  106.         s += t->tm_sec;
  107.  
  108. /* Now adjust for the time zone and possible daylight savings time */
  109.     if (timezone == -1)
  110.         tzset();
  111.         s += timezone;
  112.         if (dst == 1 && indst(t))
  113.                 s -= SECS_PER_HOUR;
  114.  
  115.         return s;
  116. }
  117.  
  118.  
  119. static struct tm the_time;
  120.  
  121. struct tm *gmtime(t)
  122.         _CONST time_t *t;
  123. {
  124.         struct tm       *stm = &the_time;
  125.         time_t  time = *t;
  126.         int     year, mday, i;
  127.  
  128.         if (time < 0)   /* negative times are bad */
  129.                 return 0;
  130.         stm->tm_wday = ((time/SECS_PER_DAY) + 4) % 7;
  131.  
  132.         year = 70;
  133.         for (;;) {
  134.                 if (time < SECS_PER_YEAR) break;
  135.                 if ((year % 4) == 0) {
  136.                         if (time < SECS_PER_LEAPYEAR)
  137.                                 break;
  138.                         else
  139.                                 time -= SECS_PER_LEAPYEAR;
  140.                 }
  141.                 else
  142.                         time -= SECS_PER_YEAR;
  143.                 year++;
  144.         }
  145.         stm->tm_year = year;
  146.         mday = stm->tm_yday = time/SECS_PER_DAY;
  147.         days_per_mth[1] = (year % 4) ? 28 : 29;
  148.         for (i = 0; mday >= days_per_mth[i]; i++)
  149.                 mday -= days_per_mth[i];
  150.         stm->tm_mon = i;
  151.         stm->tm_mday = mday + 1;
  152.         time = time % SECS_PER_DAY;
  153.         stm->tm_hour = time/SECS_PER_HOUR;
  154.         time = time % SECS_PER_HOUR;
  155.         stm->tm_min = time/SECS_PER_MIN;
  156.         stm->tm_sec = time % SECS_PER_MIN;
  157.         stm->tm_isdst = 0;
  158.  
  159.         return stm;
  160. }
  161.  
  162. /* given a standard time, convert it to a local time */
  163.  
  164. struct tm *localtime(t)
  165.         _CONST time_t *t;
  166. {
  167.         struct tm *stm;
  168.         time_t offset;  /* seconds between local time and GMT */
  169.  
  170.     if (timezone == -1) tzset();
  171.         offset = *t - timezone;
  172.         stm = gmtime(&offset);
  173.     if (stm == NULL) return stm;        /* check for illegal time */
  174.         stm->tm_isdst = (dst == -1) ? -1 : 0;
  175.  
  176.         if (dst == 1 && indst(stm)) {   /* daylight savings time in effect */
  177.                 stm->tm_isdst = 1;
  178.                 if (++stm->tm_hour > 23) {
  179.                         stm->tm_hour -= 24;
  180.                         stm->tm_wday = (stm->tm_wday + 1) % 7;
  181.                         stm->tm_yday++;
  182.                         stm->tm_mday++;
  183.                         if (stm->tm_mday > days_per_mth[stm->tm_mon]) {
  184.                                 stm->tm_mday = 1;
  185.                                 stm->tm_mon++;
  186.                         }
  187.                 }
  188.         }
  189.         return stm;
  190. }
  191.  
  192. /* set the timezone and dst flag to the local rules */
  193. void
  194. tzset()
  195. {
  196.     timezone = tzoffset(getenv("TZ"), &dst);
  197. }
  198.  
  199. /*
  200.  * determine the difference, in seconds, between the given time zone
  201.  * and Greenwich Mean. As a side effect, the integer pointed to
  202.  * by hasdst is set to 1 if the given time zone follows daylight
  203.  * savings time, 0 if there is no DST.
  204.  *
  205.  * Time zones are given as strings of the form
  206.  * "[TZNAME][h][:m][TZDSTNAME]" where h:m gives the hours:minutes
  207.  * east of GMT for the timezone (if [:m] does not appear, 0 is assumed).
  208.  * If the final field, TZDSTNAME, appears, then the time zone follows
  209.  * daylight savings time.
  210.  *
  211.  * Example: EST5EDT would represent the N. American Eastern time zone
  212.  *          CST6CDT would represent the N. American Central time zone
  213.  *          NFLD3:30NFLD would represent Newfoundland time (one and a
  214.  *              half hours ahead of Eastern).
  215.  *          OZCST-9:30 would represent the Australian central time zone.
  216.  *              (which, so I hear, doesn't have DST).
  217.  *
  218.  * NOTE: support for daylight savings time is currently very bogus.
  219.  * It's probably best to do without, unless you live in North America.
  220.  *
  221.  */
  222. static
  223. time_t tzoffset(s, hasdst)
  224.         char *s;
  225.         int  *hasdst;
  226. {
  227.         time_t off = 0;
  228.         int x, sgn = 1;
  229.  
  230.         *hasdst = -1;                   /* Assume unknown */
  231.         if (!s || !*s)
  232.                 return 0;               /* Assume GMT */
  233.         *hasdst = 0;
  234.  
  235.         while (isalpha(*s)) s++;        /* skip name */
  236.         x = 0;
  237.         if (*s == '-') {
  238.                 sgn = -1;
  239.                 s++;
  240.         }
  241.         while (isdigit(*s)) {
  242.                 x = 10 * x + toint(*s);
  243.                 s++;
  244.         }
  245.         off = x * SECS_PER_HOUR;
  246.         if (*s == ':') {
  247.                 x = 0;
  248.                 s++;
  249.                 while (isdigit(*s)) {
  250.                         x = 10 * x + toint(*s);
  251.                         s++;
  252.                 }
  253.             off += (x * SECS_PER_MIN);
  254.         }
  255.         if (isalpha(*s))
  256.                 *hasdst = 1;
  257.         return sgn * off;
  258. }
  259.  
  260. /*
  261.  * Given a tm struct representing the local time, determine whether
  262.  * DST is currently in effect. This should only be
  263.  * called if it is known that the time zone indeed supports DST.
  264.  *
  265.  * FIXME: For now, assume that everyone follows the North American
  266.  *   time zone rules, all the time. This means daylight savings
  267.  *   time is assumed to be in effect from the first Sunday in April
  268.  *   to the last Sunday in October. Prior to 1987, the old rules
  269.  *   (last Sunday in April to last Sunday in Oct.) are used, even when
  270.  *   (as in 1974) they're not applicable. Sorry.
  271.  *
  272.  */
  273.  
  274. static
  275. int indst(t)
  276.         struct tm *t;
  277. {
  278.         if (t->tm_mon == 3) {           /* April */
  279. /* before 1987, see if there's another sunday in the month */
  280.                 if (t->tm_year < 87 && t->tm_wday + 30 - t->tm_mday < 7)
  281.                         return 1;       /* no there isn't */
  282. /* after 1987, see if a sunday has happened yet */
  283.                 if (t->tm_wday - t->tm_mday < 0)
  284.                         return 1;       /* yep */
  285.                 return 0;
  286.         }
  287.         if (t->tm_mon == 9) {           /* October */
  288.                 if (t->tm_wday + 31 - t->tm_mday < 7)
  289.                         return 0;       /* there are no more sundays */
  290.                 return 1;
  291.         }
  292. /* Otherwise, see if it's a month between April and October exclusive */
  293.         return (t->tm_mon > 3 && t->tm_mon < 9);
  294. }
  295.  
  296. /* return difference between two time_t types -- ERS*/
  297.  
  298.  
  299. #ifdef __GNUC__
  300. double difftime(t1, t2)
  301. time_t t1, t2;
  302. {
  303.     return (double) (t2 - t1);
  304. }
  305. #endif
  306.